//
//  CVImageConverter.m
//  CVSampleBasic
//
//  Created by  Artem on 17.08.11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "CVImageConverter.h"


@implementation CVImageConverter

//ToDo: code normal error-related stuff

+(UIImage *)UIImageFromCVMat:(cv::Mat)cv_image withError:(NSError **)error {
    int width = cv_image.cols, height = cv_image.rows;
    int _channels = cv_image.channels();
    const uchar* data = cv_image.data;
    int step = cv_image.step;
    
    // Determine the Bytes Per Pixel
    int bpp = (_channels == 1) ? 1 : 4;
    
    // Write the data into a bitmap context
    CGContextRef context;
    CGColorSpaceRef colorSpace;
    uchar* bitmapData = NULL;
    
    if( bpp == 1 ) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    }
    else if( bpp == 4 ) {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }
    
    if( !colorSpace ) {
        *error = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain
                                             code:0 
                                         userInfo:nil] autorelease];
        return nil;
    }
    
    bitmapData = (uchar*)malloc( bpp * height * width );
    if( !bitmapData )
    {
        CGColorSpaceRelease( colorSpace );
        *error = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain
                                             code:0 
                                         userInfo:nil] autorelease];
        return nil;
        return nil;
    }
    
    context = CGBitmapContextCreate( bitmapData,
                                    width,
                                    height,
                                    8,
                                    bpp * width,
                                    colorSpace,
                                    (bpp == 1) ? kCGImageAlphaNone :
                                    kCGImageAlphaNoneSkipLast );
    CGColorSpaceRelease( colorSpace );
    if( !context )
    {
        free( bitmapData );
        *error = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain
                                             code:0 
                                         userInfo:nil] autorelease];
        return nil;
    }
    
    // Copy pixel information from data into bitmapData
    if (bpp == 4)
    {
        int           bitmapIndex = 0;
		const uchar * base        = data;
        
		for (int y = 0; y < height; y++)
		{
			const uchar * line = base + y * step;
            
		    for (int x = 0; x < width; x++)
		    {
				// Blue channel
                bitmapData[bitmapIndex + 2] = line[0];
				// Green channel
				bitmapData[bitmapIndex + 1] = line[1];
				// Red channel
				bitmapData[bitmapIndex + 0] = line[2];
                
				line        += 3;
				bitmapIndex += bpp;
			}
		}
    }
    else if (bpp == 1)
    {
		for (int y = 0; y < height; y++)
			memcpy (bitmapData + y * width, data + y * step, width);
    }
    
    // Turn the bitmap context into an imageRef
    CGImageRef imageRef = CGBitmapContextCreateImage( context );
    CGContextRelease( context );
    if( !imageRef )
    {
        free( bitmapData );
        *error = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain
                                             code:0 
                                         userInfo:nil] autorelease];
        return nil;
    }
    
  
    UIImage* image = [[UIImage alloc] initWithCGImage:imageRef];
 
    
    
 
    

    CGImageRelease( imageRef );
    free( bitmapData );
    
    return [image autorelease];  
}


@end
